#!/usr/bin/env python3
###
# @Author: Logan.Li
# @Gitee: https://gitee.com/attacker
# @email: admin@attacker.club
# @Date: 2025-03-14 10:05:30
# @LastEditTime: 2025-03-14 10:05:35
# @Description: AWS EKS监控模块
###

import logging
from typing import Dict, List
from botocore.exceptions import ClientError
from ..core import AWSMonitor

class EKSMonitor(AWSMonitor):
    """EKS监控类"""
    
    def __init__(self, config: Dict):
        super().__init__(config)
        self.namespace = "AWS/EKS"
        self.eks = self.session.client('eks')
        
    def list_clusters(self) -> List[Dict]:
        """获取所有EKS集群"""
        try:
            response = self.eks.list_clusters()
            clusters = []
            for cluster_name in response.get('clusters', []):
                cluster = self.eks.describe_cluster(name=cluster_name)
                clusters.append(cluster['cluster'])
            return clusters
        except ClientError as e:
            logging.error(f"获取EKS集群列表失败: {e}")
            return []
            
    def list_nodegroups(self, cluster_name: str) -> List[Dict]:
        """获取集群节点组列表
        
        Args:
            cluster_name: 集群名称
        """
        try:
            response = self.eks.list_nodegroups(clusterName=cluster_name)
            nodegroups = []
            for ng_name in response.get('nodegroups', []):
                ng = self.eks.describe_nodegroup(
                    clusterName=cluster_name,
                    nodegroupName=ng_name
                )
                nodegroups.append(ng['nodegroup'])
            return nodegroups
        except ClientError as e:
            logging.error(f"获取节点组列表失败: {e}")
            return []
            
    def get_cluster_metrics(self, cluster_name: str) -> Dict:
        """获取集群监控指标
        
        Args:
            cluster_name: 集群名称
        """
        dimensions = [{
            'Name': 'ClusterName',
            'Value': cluster_name
        }]
        
        metrics = {}
        metric_list = [
            ("cluster_failed_node_count", "故障节点数"),
            ("cluster_node_count", "节点总数"),
            ("cluster_control_plane_cpu_utilization", "控制面板CPU使用率"),
            ("cluster_control_plane_memory_utilization", "控制面板内存使用率")
        ]
        
        for metric_name, metric_desc in metric_list:
            data = self.get_metric_data(
                namespace=self.namespace,
                metric_name=metric_name,
                dimensions=dimensions
            )
            metrics[metric_desc] = data
            
        return metrics
        
    def get_nodegroup_metrics(self, cluster_name: str, nodegroup_name: str) -> Dict:
        """获取节点组监控指标
        
        Args:
            cluster_name: 集群名称
            nodegroup_name: 节点组名称
        """
        dimensions = [{
            'Name': 'ClusterName',
            'Value': cluster_name
        }, {
            'Name': 'NodeGroupName',
            'Value': nodegroup_name
        }]
        
        metrics = {}
        metric_list = [
            ("node_cpu_utilization", "节点CPU使用率"),
            ("node_memory_utilization", "节点内存使用率"),
            ("node_pod_count", "Pod数量"),
            ("node_disk_utilization", "节点磁盘使用率")
        ]
        
        for metric_name, metric_desc in metric_list:
            data = self.get_metric_data(
                namespace=self.namespace,
                metric_name=metric_name,
                dimensions=dimensions
            )
            metrics[metric_desc] = data
            
        return metrics
        
    def monitor_all_clusters(self) -> Dict:
        """监控所有EKS集群"""
        clusters = self.list_clusters()
        result = {
            'total_clusters': len(clusters),
            'abnormal_clusters': [],
            'abnormal_nodegroups': []
        }
        
        for cluster in clusters:
            cluster_name = cluster['name']
            cluster_status = cluster['status']
            
            # 检查集群状态
            if cluster_status != 'ACTIVE':
                result['abnormal_clusters'].append({
                    'name': cluster_name,
                    'status': cluster_status,
                    'time': cluster.get('createdAt')
                })
                continue
                
            # 获取集群指标
            metrics = self.get_cluster_metrics(cluster_name)
            
            # 检查集群异常指标
            for metric_name, data in metrics.items():
                if not data:
                    continue
                    
                values = data.get('MetricDataResults', [])
                if not values or not values[0].get('Values'):
                    continue
                    
                value = values[0]['Values'][-1]
                
                # 判断异常条件
                is_abnormal = False
                if metric_name == "控制面板CPU使用率" and value > 80:
                    is_abnormal = True
                elif metric_name == "控制面板内存使用率" and value > 85:
                    is_abnormal = True
                elif metric_name == "故障节点数" and value > 0:
                    is_abnormal = True
                
                if is_abnormal:
                    result['abnormal_clusters'].append({
                        'name': cluster_name,
                        'metric': metric_name,
                        'value': value,
                        'time': data['MetricDataResults'][0]['Timestamps'][-1]
                    })
                    
            # 检查节点组
            nodegroups = self.list_nodegroups(cluster_name)
            for nodegroup in nodegroups:
                ng_name = nodegroup['nodegroupName']
                ng_status = nodegroup['status']
                
                # 检查节点组状态
                if ng_status != 'ACTIVE':
                    result['abnormal_nodegroups'].append({
                        'cluster': cluster_name,
                        'nodegroup': ng_name,
                        'status': ng_status,
                        'time': nodegroup.get('createdAt')
                    })
                    continue
                    
                # 获取节点组指标
                ng_metrics = self.get_nodegroup_metrics(cluster_name, ng_name)
                
                # 检查节点组异常指标
                for metric_name, data in ng_metrics.items():
                    if not data:
                        continue
                        
                    values = data.get('MetricDataResults', [])
                    if not values or not values[0].get('Values'):
                        continue
                        
                    value = values[0]['Values'][-1]
                    
                    # 判断异常条件
                    is_abnormal = False
                    if metric_name == "节点CPU使用率" and value > 80:
                        is_abnormal = True
                    elif metric_name == "节点内存使用率" and value > 85:
                        is_abnormal = True
                    elif metric_name == "节点磁盘使用率" and value > 90:
                        is_abnormal = True
                    
                    if is_abnormal:
                        result['abnormal_nodegroups'].append({
                            'cluster': cluster_name,
                            'nodegroup': ng_name,
                            'metric': metric_name,
                            'value': value,
                            'time': data['MetricDataResults'][0]['Timestamps'][-1]
                        })
        
        # 只保留最异常的前5个集群和节点组
        result['abnormal_clusters'] = sorted(
            result['abnormal_clusters'],
            key=lambda x: x.get('value', 0),
            reverse=True
        )[:5]
        
        result['abnormal_nodegroups'] = sorted(
            result['abnormal_nodegroups'],
            key=lambda x: x.get('value', 0),
            reverse=True
        )[:5]
        
        return result
